package net.xxcxcxcx.xc_enhancedmob.register;

import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.mob.MobEntity;
import net.minecraft.util.ActionResult;
import net.xxcxcxcx.xc_enhancedmob.component.EnhancedBaseComponent;
import net.xxcxcxcx.xc_enhancedmob.data.MobData;
import net.xxcxcxcx.xc_enhancedmob.event.*;
import net.xxcxcxcx.xc_enhancedmob.skills.Skill;

import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

import static net.xxcxcxcx.xc_enhancedmob.effect.EffectHelper.AllEffects;

public class EventRegister {
    //本地生物实体加载时候处理服务器提前发送的数据包
    public static void Register() {
        Skill_Register();
        Effect_Register();
    }

    private static boolean haveSkill(LivingEntity livingEntity) {
        if (livingEntity instanceof MobEntity mobEntity && !mobEntity.world.isClient) {
            EnhancedBaseComponent enhancedBaseComponent = ((EnhancedBaseComponent) ((MobData) mobEntity).getComponent(EnhancedBaseComponent.class.getName()));
            return enhancedBaseComponent.hasSkills();
        }
        return false;
    }

    //技能事件注册
    public static void Skill_Register() {
        onAbilityUseCallback.EVENT.register((target) -> {
            ActionResult actionResult = ActionResult.PASS;
            if (target instanceof MobEntity mobEntity
                    && haveSkill(target)
                    && ((EnhancedBaseComponent) ((MobData) mobEntity).getComponent(EnhancedBaseComponent.class.getName())).hasSkills()) {
                List<Skill> skillList = ((EnhancedBaseComponent) ((MobData) mobEntity).getComponent(EnhancedBaseComponent.class.getName())).getSkills();
                if (skillList == null) return actionResult;
                for (Skill skill : skillList) {
                    if (!skill.onAbilityUse(mobEntity)) {
                        actionResult = ActionResult.FAIL;
                    }
                }
            }
            return actionResult;
        });
        onAttackCallback.EVENT.register((attacker, target, source, amount, ismob, remote) -> {
            ActionResult actionResult = ActionResult.PASS;
            if (attacker instanceof MobEntity mobEntity
                    && haveSkill(mobEntity)
                    && ((EnhancedBaseComponent) ((MobData) mobEntity).getComponent(EnhancedBaseComponent.class.getName())).hasSkills()) {
                List<Skill> skillList = ((EnhancedBaseComponent) ((MobData) mobEntity).getComponent(EnhancedBaseComponent.class.getName())).getSkills();
                if (skillList == null) return actionResult;
                for (Skill skill : skillList) {
                    if (!skill.onAttack(mobEntity, target, source, amount, ismob, remote)) {
                        actionResult = ActionResult.FAIL;
                    }
                }
            }
            return actionResult;
        });
        onAttributeCallback.EVENT.register((target) -> {
            ActionResult actionResult = ActionResult.PASS;
            if (target instanceof MobEntity mobEntity && ((EnhancedBaseComponent) ((MobData) mobEntity).getComponent(EnhancedBaseComponent.class.getName())).hasSkills()) {
                List<Skill> skillList = ((EnhancedBaseComponent) ((MobData) mobEntity).getComponent(EnhancedBaseComponent.class.getName())).getSkills();
                if (skillList == null) return actionResult;
                for (Skill skill : skillList) {
                    if (!skill.onAttribute(mobEntity)) {
                        actionResult = ActionResult.FAIL;
                    }
                }
            }
            return actionResult;
        });
        onDamagedCallback.EVENT.register((attacker, target, source, amount, ismob, remote) -> {
            ActionResult actionResult = ActionResult.PASS;
            if (target instanceof MobEntity mobEntity
                    && haveSkill(target)
                    && ((EnhancedBaseComponent) ((MobData) mobEntity).getComponent(EnhancedBaseComponent.class.getName())).hasSkills()) {
                List<Skill> skillList = ((EnhancedBaseComponent) ((MobData) mobEntity).getComponent(EnhancedBaseComponent.class.getName())).getSkills();
                if (skillList == null) return actionResult;
                for (Skill skill : skillList) {
                    if (!skill.onDamaged(attacker, mobEntity, source, amount, ismob, remote)) {
                        actionResult = ActionResult.FAIL;
                    }
                }
            }
            return actionResult;
        });
        onDeathCallback.EVENT.register((attacker, target, source, ismob, remote) -> {
            ActionResult actionResult = ActionResult.PASS;
            if (target instanceof MobEntity mobEntity
                    && haveSkill(target)
                    && ((EnhancedBaseComponent) ((MobData) mobEntity).getComponent(EnhancedBaseComponent.class.getName())).hasSkills()) {
                List<Skill> skillList = ((EnhancedBaseComponent) ((MobData) mobEntity).getComponent(EnhancedBaseComponent.class.getName())).getSkills();
                if (skillList == null) return actionResult;
                for (Skill skill : skillList) {
                    if (!skill.onDeath(attacker, mobEntity, source, ismob, remote)) {
                        actionResult = ActionResult.FAIL;
                    }
                }
            }
            return actionResult;
        });
        onStartAttackCallback.EVENT.register((attacker, target) -> {
            ActionResult actionResult = ActionResult.PASS;
            if (attacker instanceof MobEntity mobEntity
                    && haveSkill(mobEntity)
                    && ((EnhancedBaseComponent) ((MobData) mobEntity).getComponent(EnhancedBaseComponent.class.getName())).hasSkills()) {
                List<Skill> skillList = ((EnhancedBaseComponent) ((MobData) mobEntity).getComponent(EnhancedBaseComponent.class.getName())).getSkills();
                if (skillList == null) return actionResult;
                for (Skill skill : skillList) {
                    if (!skill.onStartAttack(mobEntity, target)) {
                        actionResult = ActionResult.FAIL;
                    }
                }
            }
            return actionResult;
        });
        onTreatCallback.EVENT.register((target, amount) -> {
            ActionResult actionResult = ActionResult.PASS;
            if (target instanceof MobEntity mobEntity
                    && haveSkill(target)
                    && ((EnhancedBaseComponent) ((MobData) mobEntity).getComponent(EnhancedBaseComponent.class.getName())).hasSkills()) {
                List<Skill> skillList = ((EnhancedBaseComponent) ((MobData) mobEntity).getComponent(EnhancedBaseComponent.class.getName())).getSkills();
                if (skillList == null) return actionResult;
                for (Skill skill : skillList) {
                    if (!skill.onTreat(mobEntity, amount)) {
                        actionResult = ActionResult.FAIL;
                    }
                }
            }
            return actionResult;
        });
        passiveApplyCallback.EVENT.register((target) -> {
            ActionResult actionResult = ActionResult.PASS;
            if (target instanceof MobEntity mobEntity
                    && haveSkill(target)
                    && ((EnhancedBaseComponent) ((MobData) mobEntity).getComponent(EnhancedBaseComponent.class.getName())).hasSkills()) {
                List<Skill> skillList = ((EnhancedBaseComponent) ((MobData) mobEntity).getComponent(EnhancedBaseComponent.class.getName())).getSkills();
                if (skillList == null) return actionResult;
                for (Skill skill : skillList) {
                    if (!skill.passiveApply(mobEntity)) {
                        actionResult = ActionResult.FAIL;
                    }
                }
            }
            return actionResult;
        });
    }

    //药水效果事件注册
    public static void Effect_Register() {
        onAbilityUseCallback.EVENT.register((target) -> {
            AtomicReference<ActionResult> actionResult = new AtomicReference<>(ActionResult.PASS);
            AllEffects.forEach(effectMaker -> {
                if (target.hasStatusEffect(effectMaker.getStatusEffect())) {
                    int level = target.getStatusEffect(effectMaker.getStatusEffect()).getAmplifier();
                    if (!effectMaker.geteffetEvent().onAbilityUse(target, level)) {
                        actionResult.set(ActionResult.FAIL);
                    }
                }
            });
            return actionResult.get();
        });
        onAttackCallback.EVENT.register((attacker, target, source, amount, ismob, remote) -> {
            AtomicReference<ActionResult> actionResult = new AtomicReference<>(ActionResult.PASS);
            AllEffects.forEach(effectMaker -> {
                if (target.hasStatusEffect(effectMaker.getStatusEffect())) {
                    int level = target.getStatusEffect(effectMaker.getStatusEffect()).getAmplifier();
                    if (!effectMaker.geteffetEvent().onAttack(attacker, target, source, amount, ismob, remote, level)) {
                        actionResult.set(ActionResult.FAIL);
                    }
                }
            });
            return actionResult.get();
        });
        onAttributeCallback.EVENT.register((target) -> {
            AtomicReference<ActionResult> actionResult = new AtomicReference<>(ActionResult.PASS);
            AllEffects.forEach(effectMaker -> {
                if (target.hasStatusEffect(effectMaker.getStatusEffect())) {
                    int level = target.getStatusEffect(effectMaker.getStatusEffect()).getAmplifier();
                    if (!effectMaker.geteffetEvent().onAttribute(target, level)) {
                        actionResult.set(ActionResult.FAIL);
                    }
                }
            });
            return actionResult.get();
        });
        onDamagedCallback.EVENT.register((attacker, target, source, amount, ismob, remote) -> {
            AtomicReference<ActionResult> actionResult = new AtomicReference<>(ActionResult.PASS);
            AllEffects.forEach(effectMaker -> {
                if (target.hasStatusEffect(effectMaker.getStatusEffect())) {
                    int level = target.getStatusEffect(effectMaker.getStatusEffect()).getAmplifier();
                    if (!effectMaker.geteffetEvent().onDamaged(attacker, target, source, amount, ismob, remote, level)) {
                        actionResult.set(ActionResult.FAIL);
                    }
                }
            });
            return actionResult.get();
        });
        onDeathCallback.EVENT.register((attacker, target, source, ismob, remote) -> {
            AtomicReference<ActionResult> actionResult = new AtomicReference<>(ActionResult.PASS);
            AllEffects.forEach(effectMaker -> {
                if (target.hasStatusEffect(effectMaker.getStatusEffect())) {
                    int level = target.getStatusEffect(effectMaker.getStatusEffect()).getAmplifier();
                    if (!effectMaker.geteffetEvent().onDeath(attacker, target, source, ismob, remote, level)) {
                        actionResult.set(ActionResult.FAIL);
                    }
                }
            });
            return actionResult.get();
        });
        onStartAttackCallback.EVENT.register((attacker, target) -> {
            AtomicReference<ActionResult> actionResult = new AtomicReference<>(ActionResult.PASS);
            AllEffects.forEach(effectMaker -> {
                if (target.hasStatusEffect(effectMaker.getStatusEffect())) {
                    int level = target.getStatusEffect(effectMaker.getStatusEffect()).getAmplifier();
                    if (!effectMaker.geteffetEvent().onStartAttack(attacker, target, level)) {
                        actionResult.set(ActionResult.FAIL);
                    }
                }
            });
            return actionResult.get();
        });
        onTreatCallback.EVENT.register((target, amount) -> {
            AtomicReference<ActionResult> actionResult = new AtomicReference<>(ActionResult.PASS);
            AllEffects.forEach(effectMaker -> {
                if (target.hasStatusEffect(effectMaker.getStatusEffect())) {
                    int level = target.getStatusEffect(effectMaker.getStatusEffect()).getAmplifier();
                    if (!effectMaker.geteffetEvent().onTreat(target, amount, level)) {
                        actionResult.set(ActionResult.FAIL);
                    }
                }
            });
            return actionResult.get();
        });
        passiveApplyCallback.EVENT.register((target) -> {
            AtomicReference<ActionResult> actionResult = new AtomicReference<>(ActionResult.PASS);
            AllEffects.forEach(effectMaker -> {
                if (target.hasStatusEffect(effectMaker.getStatusEffect())) {
                    int level = target.getStatusEffect(effectMaker.getStatusEffect()).getAmplifier();
                    if (!effectMaker.geteffetEvent().passiveApply(target, level)) {
                        actionResult.set(ActionResult.FAIL);
                    }
                }
            });
            return actionResult.get();
        });
    }
}
